﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LiteUart
{
    public partial class UserControl1 : UserControl
    {
        int cursorLine;
        int cursorOffset;
        int dispalyLineStart = 0;
        int displayLineCount = 15;
        int screenLineStart = 0;

        int fontWidth = 0;
        int fontHeight = 0;
        int scrollValue = 0;

        Graphics g;
        Graphics g2;
        BufferedGraphics myBuffer;
        Font fontC;
        StringFormat sf;
        SolidBrush b1;
        ArrayList lines;

        Analyzer analyzer;



        public UserControl1()
        {
            InitializeComponent();
            analyzer = new Analyzer(this);

            lines = new ArrayList(1200);
            lines.Add(new LineNode());
        }


        protected override void OnClick(EventArgs e)
        {
            //base.OnClick(e);
        }

        // protected override void OnKeyPress(KeyPressEventArgs e)
        // {
        //base.OnKeyPress(e);
        //    e.Handled = true;

        // }

        protected override void OnLoad(EventArgs e)
        {

            base.OnLoad(e);

            fontC = new Font(this.Font.FontFamily, this.Font.Size, FontStyle.Regular, this.Font.Unit);
            g = CreateGraphics();

            sf = StringFormat.GenericTypographic;
            sf.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;

            ResetResultes();

            this.vScrollBar.ValueChanged += new EventHandler(OnScrollEvent);

            ThreadStart childref = new ThreadStart(StartAnalyzer);
            Thread childThread = new Thread(childref);
            childThread.Start();
        }



        public struct Character
        {
            public char c;
        }


        class LineNode
        {
            public int MaxOffset = 0;
            public ArrayList Characters = new ArrayList();
        }

        public void StartAnalyzer()
        {
            analyzer.Run();
        }
        private void ResetResultes()
        {
            if (myBuffer != null)
            {
                myBuffer.Dispose();
            }
            if (g2 != null)
            {
                g2.Dispose();
            }
            if (g == null)
                return;

            //  Rectangle rectangle = panel1.ClientRectangle;
            Rectangle rectangle = new Rectangle(0, 0, this.Width, this.Height);
            BufferedGraphicsContext GraphicsContext = BufferedGraphicsManager.Current;
            myBuffer = GraphicsContext.Allocate(g, rectangle);

            g2 = myBuffer.Graphics;
            g2.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g2.SmoothingMode = SmoothingMode.HighQuality;

            SizeF mSizeF = g2.MeasureString("A", fontC, new PointF(0, 0), sf);
            fontHeight = (int)mSizeF.Height;
            fontWidth = (int)mSizeF.Width;
            //单色填充
            b1 = new SolidBrush(Color.White);//定义单色画刷         

            //g2.DrawRectangle
            displayLineCount = this.Height / fontHeight;

            //如果光标的位置大于可显示的总行数，那么则调整起始行与光标所在行的位置
            if (cursorLine >= displayLineCount)
            {
                //调整起始行
                dispalyLineStart += cursorLine - displayLineCount + 1;
                //将光标移动到最后一行
                cursorLine = displayLineCount - 1;
            }

          
            //this.vScrollBar.Value = (dispalyLineStart + cursorLine) * fontHeight;
        }

      

        protected  void OnScrollEvent(object sender, EventArgs e)
        {
            screenLineStart = vScrollBar.Value / fontHeight;
            Draw();
        }

        public void Draw()
        {
         

            this.BeginInvoke((EventHandler)(delegate
            {
                g2.Clear(BackColor);

                //滚动条计算
                this.vScrollBar.Maximum = (dispalyLineStart + displayLineCount) * fontHeight;
                this.vScrollBar.Minimum = 0;
                this.vScrollBar.SmallChange = fontHeight;
                this.vScrollBar.LargeChange = fontHeight * displayLineCount;

                if (scrollValue > 0) {

                    this.vScrollBar.Value += scrollValue;
                    scrollValue = 0;
                }

                int show = displayLineCount;
                if (displayLineCount + screenLineStart > lines.Count)
                {
                    show = lines.Count - screenLineStart;
                }
                for (int i = 0; i < show; i++)
                {
                    int offset = 0;

                    LineNode lineNode = (LineNode)lines[screenLineStart + i];
                    for (int j = 0; j < lineNode.Characters.Count; j++)
                    {
                        //超出后不打印
                        if (j == GetDisplayColumns())
                            break;

                        Character c = (Character)lineNode.Characters[j];
                        SizeF mSizeF = g2.MeasureString(c.c.ToString(), fontC, new PointF(0, 0), sf);
                        g2.DrawString(c.c.ToString(), fontC, b1, offset, fontHeight * i, sf);
                        offset += (int)mSizeF.Width;
                    }
                }
                myBuffer.Render(g);
            }));

        }

        public int GetDisplayRows()
        {
            return (this.Height / this.fontHeight);
        }

        public int GetDisplayColumns()
        {
            return ((this.Width-this.vScrollBar.Width) / this.fontWidth);
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (myBuffer != null)
            {
                ResetResultes();
                Draw();
            }

        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Draw();
        }
        public void Input(char[] buffer, int size)
        {
            analyzer.Write(buffer, size);
        }

        public void Write(char character)
        {

            // Console.WriteLine("写入字符"+character.ToString());

            //判断是否超出了最大的显示列，如果超出则自动换行
            if (this.cursorOffset >= GetDisplayColumns())
            {
                //移动光标到下一行
                this.MovetToNextLine();
            }
            LineNode line = (LineNode)lines[this.cursorLine + this.dispalyLineStart];
            if (this.cursorOffset < line.Characters.Count)
            {
                line.Characters[cursorOffset] = new Character
                {
                    c = character
                };
            }
            else
            {
                while (this.cursorOffset > line.Characters.Count)
                {
                    line.Characters.Add(new Character
                    {
                        c = ' '
                    });
                }

                Character character1 = new Character
                {
                    c = character
                };
                line.Characters.Add(character1);
            }
            cursorOffset++;
            if (line.MaxOffset < this.cursorOffset)
                line.MaxOffset = this.cursorOffset;

        }

        public void MoveCursorOffset(int offset)
        {
            this.cursorOffset = offset;
        }


        public void MoveCursorToNext()
        {
            this.MoveCursorOffset(this.cursorOffset + 1);
        }

        public void MoveCursorLine(int line)
        {

            if (line > displayLineCount - 1)
                line = displayLineCount - 1;

            if (line + dispalyLineStart >= lines.Count)
            {
                int count = line + dispalyLineStart + 1 - lines.Count;
                for (int i = 0; i < count; i++)
                {
                    lines.Add(new LineNode());
                }
            }

            this.cursorLine = line;
        }


        public void PostCursorOffset(int offset)
        {
            this.cursorOffset += offset;
        }
        public void PostCursorLine(int line)
        {
            this.cursorLine += line;
        }

        public void MovetToNextLine()
        {
            //光标已经移动到了下一位

            if (this.cursorLine == 1200)
            {
                lines.RemoveRange(0, 200);
                this.cursorLine -= 200;
                this.dispalyLineStart -= 200;
            }

            if (this.cursorLine == this.displayLineCount - 1)
            {
                this.dispalyLineStart += 1;
            }
            else
            {
                this.cursorLine += 1;
            }

            if (this.dispalyLineStart + this.cursorLine >= lines.Count)
            {
                lines.Add(new LineNode());
                if (screenLineStart + 1 == dispalyLineStart)
                {
                    screenLineStart++;
                    scrollValue += fontHeight;
                }
                //  Console.WriteLine("" + screenLineStart + "x" + dispalyLineStart);
            }
            this.cursorOffset = 0;
        }

        public void RemoveCursorToEnd()
        {
            LineNode line = (LineNode)lines[this.cursorLine + this.dispalyLineStart];
            line.Characters.RemoveRange(this.cursorOffset, line.Characters.Count - this.cursorOffset);

        }

        public void BeepPlay()
        {
            System.Media.SystemSounds.Beep.Play();
        }

        protected override void OnSizeChanged(EventArgs e)
        {

            ResetResultes();
            base.OnSizeChanged(e);
        }
    }
}
